﻿using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;

using GameServer.Managers;
using GameServer.Networking;
using GameServer.Networking.Packets;
using GameServer.Virtual_Objects.User.Inventory;
using GameServer.Virtual_Objects.Room;

namespace GameServer.Virtual_Objects.User
{
    class virtualUser
    {
        public int UserID;
        public int SessionID;
        public int Rank;

        public int SpectatorID = -1;
        public bool isSpectating = false;
        public string Nickname;
        public string Username;
        public int Channel = 1;
        public int Page = 0;
        public int ClanID = -1;
        public int ClanRank = -1;
        public string ClanName = "NULL";

        public int Premium = 0;
        public long PremiumExpire = -1;

        public int Cash = 0;
        public int Exp = 0;
        public int ExpUP = 0;
        public int DinarUP = 0;
        public int Dinar = 0;
        public int Health = 1000;
        public int Kills = 0;
        public int Plantings = 0;
        public int Rockets = 0;
        public bool isSpawned = false;
        public int Granade = 0;
        public int killFromSpawn = 0;
        public int Deaths = 0;
        public string Class = "1";
        public int Weapon = 1;
        public int Coupons = 0;
        public int TodayCoupon = 0;
        public int droppedFlash = 0;
        public int droppedM14 = 0;
        public int droppedAmmo = 0;
        public bool GMMode = false;
        public bool PCItem = false;
        public bool hasTrinityGuardCheck = false;
        public bool hasExpUp1 = false;
        public bool hasExpUp2 = false;
        public long LastTimeStamp = 0;
        public int userListPage = 0;
        public int InvitationBy = -1;
        public DateTime pingServer = DateTime.Now;
        public string HWID = "NULL";
        //Engineer
        public string CostumeE = "BA11,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^";
        //Medic
        public string CostumeM = "BA12,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^";
        //Sniper
        public string CostumeS = "BA13,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^";
        //Assault
        public string CostumeA = "BA14,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^";
        //Heavy
        public string CostumeH = "BA15,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^";

        public int SpawnProtection = 0;
        public Vehicle currentVehicle = null;
        public IPEndPoint RemoteNetwork = null;

        public ArrayList LeftItems = new ArrayList();
        public bool isMuted = false;
        public int MutedTime = 0;

        ~virtualUser()
        {
            GC.Collect();
        }

        public string[] cCodes6th = new string[6];

        public void AddCostume(string Item, int Days)
        {
            int InventorySlot = -1;
            for (int I = 0; I < 30; I++)
            {
                if (Costume[I] == null) { InventorySlot = I; break; }
            }
            if (InventorySlot >= 0)
            {
                if (hasCostume(Item))
                {
                    //if user have item
                    CostumeItem bItem = null;
                    foreach (CostumeItem II in Costume)
                    {
                        if (II != null) { if (II._Code.ToLower() == Item.ToLower()) { bItem = II; } }
                    }

                    if (bItem != null)
                    {
                        DateTime ItemTime = DateTime.ParseExact(bItem._StartTime.ToString(), "yyMMddHH", null);
                        ItemTime = ItemTime.AddDays(Days);
                        long StartTime = long.Parse(String.Format("{0:yyMMddHH}", ItemTime));
                        bItem._StartTime = StartTime;
                        DB.runQuery("UPDATE inventory_costume SET expiredate='" + bItem._StartTime + "' WHERE ownerid='" + UserID + "' AND itemcode='" + Item + "'");
                        Costume = new CostumeItem[35];
                    }
                }
                else
                {
                    DateTime current = DateTime.Now;
                    current = current.AddDays(Days);
                    current = current.AddHours(-1);
                    int StartTime = int.Parse(String.Format("{0:yyMMddHH}", current));
                    DB.runQuery("INSERT INTO inventory_costume (`ownerid`, `expiredate`, `itemcode`, `deleted`) VALUES ('" + UserID.ToString() + "', '" + StartTime.ToString() + "', '" + Item + "', '0')");
                    Costume[InventorySlot] = new CostumeItem(StartTime, Item);
                    Costume = new CostumeItem[35];
                }
            }
            else
                send(new PACKET_ITEMSHOP(PACKET_ITEMSHOP.ErrorCodes.InventoryFull, "null"));
        }

        public void AddItem(string Item, int Days)
        {
            int InventorySlot = -1;
            for (int I = 0; I < 30; I++)
            {
                if (Inventory[I] == null) { InventorySlot = I; break; }
            }
            if (InventorySlot >= 0)
            {
                if (hasItem(Item))
                {
                    //if user have item
                    InventoryItem bItem = null;
                    foreach (InventoryItem II in Inventory)
                    {
                        if (II != null) { if (II._Code.ToLower() == Item.ToLower()) { bItem = II; } }
                    }

                    if (bItem != null)
                    {
                        DateTime ItemTime = DateTime.ParseExact(bItem._StartTime.ToString(), "yyMMddHH", null);
                        ItemTime = ItemTime.AddDays(Days);
                        long StartTime = long.Parse(String.Format("{0:yyMMddHH}", ItemTime));
                        bItem._StartTime = StartTime;
                        DB.runQuery("UPDATE inventory SET expiredate='" + bItem._StartTime + "' WHERE ownerid='" + UserID + "' AND itemcode='" + Item + "'");

                    }
                }
                else
                {
                    DateTime current = DateTime.Now;
                    current = current.AddDays(Days);
                    current = current.AddHours(-1);
                    int StartTime = int.Parse(String.Format("{0:yyMMddHH}", current));
                    DB.runQuery("INSERT INTO inventory (`ownerid`, `expiredate`, `itemcode`, `deleted`) VALUES ('" + UserID.ToString() + "', '" + StartTime.ToString() + "', '" + Item + "', '0')");
                    Inventory[InventorySlot] = new InventoryItem(StartTime, Item);
                }
            }
            else
                send(new PACKET_ITEMSHOP(PACKET_ITEMSHOP.ErrorCodes.InventoryFull, "null"));
        }

        public void RemoveItem(string Weapon)
        {
            if (hasItem(Weapon))
            {
                int CalculateInventoryID = getInventoryID(Weapon);

                string InventoryCode = "I00" + CalculateInventoryID;

                if (CalculateInventoryID >= 10) InventoryCode = "I0" + CalculateInventoryID;

                Log.WriteLine(InventoryCode);

                for (int I = 0; I < 5; I++)
                {
                    for (int J = 0; J < 8; J++)
                    {
                        if (Equipment[I, J] == InventoryCode)
                        {
                            Equipment[I, J] = "^";

                            StringBuilder Items = new StringBuilder();
                            for (int X = 0; X < 8; X++)
                            {
                                Items.Append(Equipment[I, X] + ",");
                            }
                            string EquipStr = Items.ToString().Remove(Items.ToString().Length - 1);
                            DB.runQuery("UPDATE equipment SET class" + I.ToString() + "='" + EquipStr[J] + "' WHERE ownerid='" + UserID + "'");
                        }
                    }
                }
            }
        }

        public string getSlots()
        {
            string UserSlots = "F,F,F,F";
            string[] Slots = UserSlots.Split(new char[] { ',' });
            if (hasItem("CA01") || Premium >= 3)
                Slots[0] = "T";
            if (hasItem("DS05") || hasItem("DS10") || hasItem("DV01") || hasItem("DS01") || hasItem("DU05") || hasItem("DU01") || hasItem("DU02") || hasItem("DS03"))
                Slots[1] = "T";
            if (hasItem("CA03"))
                Slots[2] = "T";
            if (PCItem || hasItem("CA04"))
                Slots[3] = "T";
            UserSlots = string.Join(",", Slots);
            return UserSlots;
        }

        public void reloadCash()
        {
            string[] _Cash = DB.runReadRow("SELECT cash FROM users WHERE id='" + UserID + "'");
            Cash = int.Parse(_Cash[0]);
        }

        public bool CheckForEvent(int EventID)
        {
            int EventCheck = DB.runRead("SELECT * FROM users_events WHERE userid='" + UserID + "' AND eventid='" + EventID + "'", null);
            if (EventCheck == 0)
            {
                return false;
            }
            return true;
        }

        public StringBuilder rebuildWeaponList()
        {
            int ItemCount = 0;

            StringBuilder WeaponList = new StringBuilder();
            for (int I = 0; I < 30; I++)
            {
                if (Inventory[I] != null)
                {
                    InventoryItem _Inv = Inventory[I];
                    TimeSpan ExpireTime = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(_Inv._StartTime);

                    WeaponList.Append(_Inv._Code.ToUpper() + "-3-0-" + _Inv._StartTime + "-0-0-0-0-0-9999-9999,");/*+ ExpireTime.TotalSeconds +*/
                    ItemCount++;
                }
            }

            for (int J = 0; J < (30 - ItemCount); J++)
            {
                WeaponList.Append("^,");
            }
            return WeaponList;
        }

        public void reloadInventory()
        {
            try
            {
                for (int Class = 0; Class < 5; Class++)
                {
                    if (cCodes6th[Class].Contains("-"))
                    {
                        string[] CodeInfo = cCodes6th[Class].Split(new char[] { '-' });
                        int[] CodeInfoIDs = new int[2];
                        CodeInfoIDs[0] = getInventoryID(CodeInfo[0]);
                        CodeInfoIDs[1] = getInventoryID(CodeInfo[1]);

                        string[] newCodeInfo = new string[2];

                        /* 
                         * Parse New Code Info *
                         */
                        if (CodeInfoIDs[0] >= 10)
                        {
                            newCodeInfo[0] = "I0" + CodeInfoIDs[0];
                        }
                        else { newCodeInfo[0] = "I00" + CodeInfoIDs[0]; }
                        if (CodeInfoIDs[1] >= 10)
                        {
                            newCodeInfo[1] = "I0" + CodeInfoIDs[1];
                        }
                        else { newCodeInfo[1] = "I00" + CodeInfoIDs[1]; }

                        string newBuildItemCode = string.Join("-", newCodeInfo);

                        Equipment[Class, 5] = newBuildItemCode;

                        if (!CodeInfo[0].Contains("DU01") && !CodeInfo[0].Contains("DS05") && !CodeInfo[0].Contains("DV01") && !CodeInfo[0].Contains("DS01") && !CodeInfo[0].Contains("DS03") && !CodeInfo[0].Contains("DU02") && !CodeInfo[0].Contains("DS10"))
                        {
                            Equipment[Class, 5] = "^";
                        }

                        if (!CodeInfo[1].Contains("DU01") && !CodeInfo[1].Contains("DS05") && !CodeInfo[1].Contains("DV01") && !CodeInfo[1].Contains("DS01") && !CodeInfo[1].Contains("DS03") && !CodeInfo[1].Contains("DU02") && !CodeInfo[1].Contains("DS10"))
                        {
                            Equipment[Class, 5] = "^";
                        }

                        StringBuilder Items = new StringBuilder();
                        for (int I = 0; I < 8; I++)
                        {
                            Items.Append(Equipment[Class, I] + ",");
                        }
                        string EquipStr = Items.ToString().Remove(Items.ToString().Length - 1);
                        send(new PACKET_EQUIPMENT(Class, EquipStr));
                        DB.runQuery("UPDATE equipment SET class" + Class + "='" + EquipStr + "' WHERE ownerid='" + UserID.ToString() + "'");
                    }
                }
            }
            catch { }
        }


        public void LoadItems()
        {
            try
            {
                reloadInventory();
                DateTime current = DateTime.Now;
                int StartTime = int.Parse(String.Format("{0:yyMMddHH}", current));

                string[] Skin = DB.runReadRow("SELECT class_0,class_1,class_2,class_3,class_4 FROM users_costumes WHERE ownerid='" + UserID + "'");
                if (Skin.Length > 0)
                {
                    CostumeE = Skin[0];
                    CostumeM = Skin[1];
                    CostumeS = Skin[2];
                    CostumeA = Skin[3];
                    CostumeH = Skin[4];
                }

                int[] checkCostumeIDs = DB.runReadColumn("SELECT id FROM inventory_costume WHERE ownerid='" + UserID.ToString() + "' AND deleted='0'", 0, null);
                for (int I = 0; I < checkCostumeIDs.Length; I++)
                {
                    string[] itemData = DB.runReadRow("SELECT expiredate, itemcode FROM inventory_costume WHERE id=" + checkCostumeIDs[I].ToString());
                    if (int.Parse(itemData[0]) < StartTime)
                    {
                        int InvItems = 0;
                        foreach (CostumeItem _InvItem in Costume)
                        {
                            if (_InvItem != null) InvItems++;
                        }
                        if (InvItems > 30)
                        {
                            DB.runQuery("DELETE FROM inventory_costume WHERE ownerid='" + UserID.ToString() + "'");
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Your inventory was resetted due too many weapons!", 999, "NULL"));
                            Inventory = new InventoryItem[35];
                        }
                        DB.runQuery("DELETE FROM inventory_costume WHERE ownerid='" + UserID.ToString() + "' AND itemcode='" + itemData[1] + "'");
                    }
                }

                int[] checkItemIDs = DB.runReadColumn("SELECT id FROM inventory WHERE ownerid='" + UserID.ToString() + "' AND deleted='0'", 0, null);
                for (int I = 0; I < checkItemIDs.Length; I++)
                {
                    string[] itemData = DB.runReadRow("SELECT expiredate, itemcode FROM inventory WHERE id=" + checkItemIDs[I].ToString());
                    if (int.Parse(itemData[0]) < StartTime)
                    {
                        int InvItems = 0;
                        foreach (InventoryItem _InvItem in Inventory)
                        {
                            if (_InvItem != null) InvItems++;
                        }
                        if (InvItems > 30)
                        {
                            DB.runQuery("DELETE FROM inventory WHERE ownerid='" + UserID.ToString() + "'");
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Your costume's inventory was resetted due too many weapons!", 999, "NULL"));
                            Costume = new CostumeItem[35];
                        }
                        DB.runQuery("DELETE FROM inventory WHERE ownerid='" + UserID.ToString() + "' AND itemcode='" + itemData[1] + "'");
                    }
                }

                int[] costumeIDs = DB.runReadColumn("SELECT id FROM inventory_costume WHERE ownerid ='" + UserID.ToString() + "' AND deleted='0'", 0, null);
                for (int I = 0; I < costumeIDs.Length; I++)
                {
                    try
                    {
                        string[] itemData = DB.runReadRow("SELECT expiredate, itemcode FROM inventory_costume WHERE id=" + costumeIDs[I].ToString());
                        Costume[I] = new CostumeItem(int.Parse(itemData[0]), itemData[1].ToLower());
                    }
                    catch
                    {
                    }
                }

                int[] itemIDs = DB.runReadColumn("SELECT id FROM inventory WHERE ownerid ='" + UserID.ToString() + "' AND deleted='0'", 0, null);
                for (int I = 0; I < itemIDs.Length; I++)
                {
                    try
                    {
                        if (Program.ESL == false)
                        {
                            string[] itemData = DB.runReadRow("SELECT expiredate, itemcode FROM inventory WHERE id=" + itemIDs[I].ToString());
                            Inventory[I] = new InventoryItem(int.Parse(itemData[0]), itemData[1].ToLower());
                        }
                    }
                    catch
                    {
                    }
                }

                if (Program.ESL)
                {
                    /*ESL*/
                    Inventory[0] = new InventoryItem(99999999, "DF95");
                    Inventory[1] = new InventoryItem(99999999, "DE07");
                    Inventory[2] = new InventoryItem(99999999, "DG63");
                    Inventory[3] = new InventoryItem(99999999, "DB63");
                    Inventory[4] = new InventoryItem(99999999, "DJ13");
                    Inventory[5] = new InventoryItem(99999999, "DC03");
                    Inventory[6] = new InventoryItem(99999999, "DC10");
                    Inventory[7] = new InventoryItem(99999999, "DF03");
                    Inventory[8] = new InventoryItem(99999999, "DF02");
                    Inventory[8] = new InventoryItem(99999999, "CA01");
                    reloadInventory();
                    /*END*/
                }

                string[] _CostumeE = CostumeE.Split(new char[] { ',' });
                string[] _CostumeM = CostumeM.Split(new char[] { ',' });
                string[] _CostumeS = CostumeS.Split(new char[] { ',' });
                string[] _CostumeA = CostumeA.Split(new char[] { ',' });
                string[] _CostumeH = CostumeH.Split(new char[] { ',' });

                if (hasCostume(_CostumeE[0]) == false) { CostumeE = "BA01,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^"; DB.runQuery("UPDATE users_costumes SET class_0='" + CostumeE + "' WHERE ownerid='" + UserID + "'"); }
                if (hasCostume(_CostumeM[0]) == false) { CostumeM = "BA02,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^"; DB.runQuery("UPDATE users_costumes SET class_1='" + CostumeM + "' WHERE ownerid='" + UserID + "'"); }
                if (hasCostume(_CostumeS[0]) == false) { CostumeS = "BA03,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^"; DB.runQuery("UPDATE users_costumes SET class_2='" + CostumeS + "' WHERE ownerid='" + UserID + "'"); }
                if (hasCostume(_CostumeA[0]) == false) { CostumeA = "BA04,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^"; DB.runQuery("UPDATE users_costumes SET class_3='" + CostumeA + "' WHERE ownerid='" + UserID + "'"); }
                if (hasCostume(_CostumeH[0]) == false) { CostumeH = "BA05,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^"; DB.runQuery("UPDATE users_costumes SET class_4='" + CostumeH + "' WHERE ownerid='" + UserID + "'"); }

                string[] newEquipString = new string[5];
                for (int I = 0; I < 5; I++)
                {
                    newEquipString[I] = Equipment[I, 5];
                }

                bool forcesave = false;
                string[] equipment = DB.runReadRow("SELECT class0, class1, class2, class3, class4 FROM equipment WHERE ownerid=" + UserID.ToString());
                for (int I = 0; I < 5; I++)
                {
                    string[] slotItems = equipment[I].Split(new char[] { ',' });
                    for (int J = 0; J < slotItems.Length; J++)
                    {
                        if (hasItem(slotItems[J]) || slotItems[J] == "^" || (slotItems[J] == "DA02" && J == 0) || (slotItems[J] == "DB01" && J == 1)
                    || (slotItems[J] == "DF01" && J == 2 && (I == 0 || I == 1)) || (slotItems[J] == "DG05" && J == 2 && I == 2) || (slotItems[J] == "DC02" && J == 2 && I == 3) || (slotItems[J] == "DJ01" && J == 2 && I == 4)
                    || (slotItems[J] == "DR01" && I == 0 && J == 3) || (slotItems[J] == "DQ01" && I == 1 && J == 3) || (slotItems[J] == "DN01" && (I == 2 || I == 3) && J == 3) || (slotItems[J] == "DL01" && I == 4 && J == 3))
                        {
                            Equipment[I, J] = slotItems[J];
                        }
                        else
                        {
                            if (slotItems[J].Contains("-") || slotItems[J].Contains("I0"))
                            {
                                Equipment[I, J] = slotItems[J];
                            }
                            else
                            {
                                Equipment[I, J] = "^";
                                forcesave = true;
                            }
                        }
                    }
                }

                for (int I = 0; I < 5; I++)
                {
                    Equipment[I, 5] = newEquipString[I];
                }

                if (Program.ESL == false)
                {
                    if (PCItem)
                    {
                        Equipment[0, 7] = "D501";
                        Equipment[1, 7] = "D602";
                        Equipment[2, 7] = "DG13";
                        Equipment[3, 7] = "D801";
                        Equipment[4, 7] = "D902";
                    }
                    else
                    {
                        //8th Slot Retails for all :)
                        if (Equipment[0, 7] == "^")
                            Equipment[0, 7] = "DF02"; //Engineer
                        if (Equipment[1, 7] == "^")
                            Equipment[1, 7] = "DQ02"; //Medic
                        if (Equipment[2, 7] == "^")
                            Equipment[2, 7] = "DB03"; //Sniper
                        if (Equipment[3, 7] == "^")
                            Equipment[3, 7] = "DB03"; //Assault
                        if (Equipment[4, 7] == "^")
                            Equipment[4, 7] = "DB03"; //Heavy
                    }
                }
                int RetailID = DB.runRead("SELECT id FROM users_retails WHERE userid='" + UserID + "'", null);
                if (RetailID > 0)
                {
                    string[] RetailData = DB.runReadRow("SELECT class, code FROM users_retails WHERE id='" + RetailID.ToString() + "'");
                    for (int I = 0; I < 5; I++)
                    {
                        if (Equipment[I, 7] == "^")
                        {
                            Equipment[I, 7] = "DB03";
                        }
                    }
                    if (Equipment[1, 7] == "^")
                    {
                        Equipment[1, 7] = "DQ02";
                    }
                    RetailClass = int.Parse(RetailData[0]);
                    Retail = RetailData[1];
                    Equipment[RetailClass, 7] = RetailData[1];
                }
            }
            catch (Exception ex)
            {
                Log.WriteError("Error: " + ex.Message + " while loading item!");
            }
        }

        #region Equipment & Inventory
        public string[,] Equipment = new String[5, 8];
        public InventoryItem[] Inventory = new InventoryItem[30];
        public CostumeItem[] Costume = new CostumeItem[60];
        public string Retail = "";
        public int RetailClass = -1;
        public bool hasRetail() { return (Retail.Length > 0); }
        public bool hasRetail(string ItemCode) { return ItemCode.ToLower().Equals(Retail.ToLower()); }
        #endregion

        #region Room Information

        public virtualRoom Room = null;
        public virtualClan Clan = null;
        public int RoomSlot = 0;
        public bool isInRoom = false;
        public bool isReady = false;
        public bool isReadyForNextRound = false;
        public int rKills = 0;
        public int rPoints = 0;
        public int rSkillPoints = 0;
        public int rDeaths = 0;

        public int rFlags = 0;
        public int rAssists = 0;

        public int ExpEarned = 0;
        public int DinarEarned = 0;
        public int EarnedPoints = 0;

        #endregion

        #region Peer2Peer
        private IPEndPoint _RemoteEndPoint;
        private IPEndPoint _LocalEndPoint;

        public long uniqID = 0L;
        public long uniqID2 = 0L;
        public int uniqIDisCRC = 0;

        public int iLocalPort = 0;
        public int iNetworkPort = 0;
        public long lLocalIP = 0;
        public long lNetworkIP = 0;

        #endregion

        public long PremiumTimeLeft()
        {
            try
            {
                if (PremiumExpire > Program.currTimeStamp)
                {
                    return PremiumExpire - Program.currTimeStamp;
                }
                else if (Premium > 0)
                {
                    DB.runQuery("UPDATE users SET premium =  '0', premiumExpire =  '-1' WHERE id=" + UserID);
                    Premium = 0;

                    return -1;
                }
                return -1;
            }
            catch { return -1; }
        }

        public void CouponLoop()
        {
            try
            {
                while (true)
                {
                    Thread.Sleep(1800000);
                    string[] isOnlineUser = DB.runReadRow("SELECT online FROM users WHERE id='" + UserID + "'");
                    if (isOnlineUser[0].Equals("1"))
                    {
                        if (TodayCoupon < 5)
                        {
                            TodayCoupon++;
                            Coupons++;
                            DB.runQuery("UPDATE users SET coupons='" + Coupons + "' WHERE id='" + UserID + "'");
                            DB.runQuery("UPDATE users SET todaycoupon='" + TodayCoupon + "' WHERE id='" + UserID + "'");
                            send(new PACKET_COUPON_EVENT(TodayCoupon, Coupons));
                        }
                    }
                }
            }
            catch { }
        }

        public virtualUser(int SessionID, int SocketID, Socket uSocket)
        {
            try
            {
                this.SocketID = SocketID;
                this.uSocket = uSocket;
                this.SessionID = SessionID;
                
				// Added Logs Connections in DataBase
                DB.runQuery("INSERT INTO log_connections (`timestamp`, `server`, `status`, `ip`, `host`) VALUES ('" + Program.currTimeStamp + "', '"+Config.SERVER_ID.ToString()+"', '0', '" + this.IPAddr + "', '" + this.Hostname + "');");

                #region Inventory System
                for (int I = 0; I < Inventory.Length; I++)
                {
                    Inventory[I] = null;
                }
                #endregion

                #region Equipment Reset System
                for (int Class = 0; Class < 5; Class++)
                {
                    for (int Slot = 0; Slot < 8; Slot++)
                    {
                        if (Slot == (int)Slots.Hands)
                            Equipment[Class, Slot] = "DA02"; //Knuckle
                        else if (Slot == (int)Slots.HandGun)
                            Equipment[Class, Slot] = "DB01"; //Colt
                        else if (Slot == (int)Slots.Weapon1)
                        {
                            switch (Class)
                            {
                                case (int)Classes.Engeneer:
                                case (int)Classes.Medic:
                                    Equipment[Class, Slot] = "DF01"; // MP7
                                    break;
                                case (int)Classes.Sniper:
                                    Equipment[Class, Slot] = "DG05";
                                    break;
                                case (int)Classes.Assault:
                                    Equipment[Class, Slot] = "DC02"; // K2
                                    break;
                                case (int)Classes.Heavy:
                                    Equipment[Class, Slot] = "DJ01";
                                    break;
                            }
                        }
                        else if (Slot == (int)Slots.Equipment)
                        {
                            switch (Class)
                            {
                                case (int)Classes.Engeneer:
                                    Equipment[Class, Slot] = "DR01"; // Spanner
                                    break;
                                case (int)Classes.Medic:
                                    Equipment[Class, Slot] = "DQ01"; // Medic Kit 1
                                    break;
                                case (int)Classes.Sniper:
                                case (int)Classes.Assault:
                                    Equipment[Class, Slot] = "DN01"; // Grenade
                                    break;
                                case (int)Classes.Heavy:
                                    Equipment[Class, Slot] = "DL01"; // Mine
                                    break;
                            }
                        }
                        else
                            Equipment[Class, Slot] = "^";
                    }
                }
                #endregion

                send(new PACKET_CONNECT());
                uSocket.BeginReceive(dataBuffer, 0, dataBuffer.Length, SocketFlags.None, new AsyncCallback(arrivedData), null);
                Thread _CouponThread = new Thread(CouponLoop);
                _CouponThread.Priority = ThreadPriority.AboveNormal;
                _CouponThread.Start();
            }
            catch (Exception ex)
            {
                Log.WriteError("Error setting up a new virtualUser: " + ex.Message);
            }
        }

        public bool hasCostume(string strCode)
        {
            try
            {
                foreach (CostumeItem II in Costume)
                {
                    if (strCode == "BA01" || strCode == "BA02" || strCode == "BA03" || strCode == "BA04" || strCode == "BA05") return true;
                    if (II != null) { if (II._Code.ToLower() == strCode.ToLower()) { return true; } }
                }
                return false;
            }
            catch { return false; }
        }

        public bool hasItem(string strCode)
        {
            try
            {
                foreach (InventoryItem II in Inventory)
                {
                    if (II != null) { if (II._Code.ToLower() == strCode.ToLower()) { return true; } }
                }
                return false;
            }
            catch { return false; }
        }

        #region Commands
        public bool isCommand(string Command)
        {
            try
            {
                string[] args = Command.Split(Convert.ToChar(0x20));

                switch (args[0].Substring(1).ToLower())
                {
                    case " ": { break; }
                    case "kickall":
                        {
                            if (Rank < 3) return true;
                            foreach (virtualUser Players in UserManager.getAllUsers())
                            {
                                Players.disconnect();
                            }
                            return true;
                        }
                    case "clean":
                        {
                            if (Rank < 6) return true;
                            Room.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Room Removed!", 999, "NULL"));
                            Room.remove();
                            return true;
                        }
                    case "notice":
                        {
                            if (Rank < 3) return true;

                            foreach (virtualUser Player in UserManager.getAllUsers())
                            {
                                Player.send(new PACKET_CHAT(Player, PACKET_CHAT.ChatType.Notice1, " [GM]NOTICE: " + Command.Substring(7), 100, "Server"));
                            }

                            return true;
                        }
                    case "extendtime":
                        {
                            if (Rank < 3) return true;

                            if (Room != null)
                            {
                                if (Room.RoomStatus != 1)
                                {
                                    Room.RoundTimeLeft += int.Parse(args[1]) * 60000;
                                    Room.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Round Time extended with " + int.Parse(args[1]).ToString() + " minutes!", 999, "NULL"));
                                }
                            }
                            return true;
                        }
                    case "reload":
                        {
                            if (Rank < 5) return true;

                            if (ItemManager.Load())
                            {
                                send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Item Manager is been reloaded!", 999, "NULL"));
                            }
                            else
                            {
                                send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Failed to reload the Item Manager.", 999, "NULL"));
                            }
                            return true;
                        }
                    case "changepassword":
                        {
                            try
                            {
                                string[] userData = DB.runReadRow("SELECT password, salt FROM users WHERE id='" + UserID + "'");
                                string oldPassword = Program.hashMD5(Program.hashMD5(args[1]) + Program.hashMD5(userData[1]));
                                string newPassword = Program.hashMD5(Program.hashMD5(args[2]) + Program.hashMD5(userData[1]));
                                string confirmNewPasssword = Program.hashMD5(Program.hashMD5(args[3]) + Program.hashMD5(userData[1]));
                                if (args[2].Length < 6 || args[2].Length > 12)
                                {
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> New password must be from 6 characters to max 12!!!", 999, "NULL"));
                                    return true;
                                }
                                else if (oldPassword != userData[0])
                                {
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Old password it's not right!!", 999, "NULL"));
                                    return true;
                                }
                                else if (newPassword != confirmNewPasssword)
                                {
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> New password and confirmation are not same!!", 999, "NULL"));
                                    return true;
                                }
                                else if (oldPassword == newPassword)
                                {
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Old password and New password are the same!!", 999, "NULL"));
                                    return true;
                                }
                                else
                                {
                                    DB.runQuery("UPDATE users SET password='" + newPassword + "' WHERE id='" + UserID + "'");
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Password changed from: " + args[1] + " to: " + args[2] + " successfully!", 999, "NULL"));
                                    return true;
                                }
                            }
                            catch
                            {
                                send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> /changepassword <oldPassword> <newPassword> <confirmationPassword>!!", 999, "NULL"));
                                return true;
                            }
                        }
                    case "endgame":
                        {
                            if (Rank < 3) return true;

                            if (Room != null)
                            {
                                if (Room.RoomStatus != 1)
                                {
                                    Room.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Ending Game!", 999, "NULL"));
                                    System.Threading.Thread.Sleep(2000);
                                    Room.endGame();
                                }
                            }
                            break;
                        }
                    case "uptime":
                        {
                            TimeSpan _StartTime = DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime;
                            send(new PACKET_MESSAGE_BOX("Online_since_" + _StartTime.Days.ToString() + "_days,_" + _StartTime.Hours.ToString() + "_hours,_" + _StartTime.Minutes.ToString() + "_minutes_:)"));
                            break;
                        }
                    case "gmmode":
                        {
                            if (Rank < 3) return false;
                            if (GMMode == true)
                            {
                                send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> GM Mode turned off", SessionID, Nickname));
                                GMMode = false;
                            }
                            else if (GMMode == false)
                            {
                                send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> GM Mode turned on", SessionID, Nickname));
                                GMMode = true;
                            }
                            return true;
                        }
                    case "clancmd":
                        {
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> Clan CMD's are: ", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> /createclan <clan name>", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> /disbandclan", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> /leaveclan", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> /kickfromclan <nickname>", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> /invite <nickname>", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> /accept or /decline", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> /upgrade (costs 10,000 cash!)", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> /changeclanname <new clan name> (costs 5,000 cash!)", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> /myclan", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> /setclanrank <nickname> <clan rank> (member, operator, leutnant)", SessionID, Nickname));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> For ClanWar rooms create a room with name starting 'CW|'", SessionID, Nickname));
                            return true;
                        }
                    case "myclan":
                        {
                            if (ClanID != -1)
                            {
                                send(new PACKET_CHAT("ClanSystem", PACKET_CHAT.ChatType.Clan, "ClanSystem >> Clan Informations below:", ClanID, Nickname));
                                send(new PACKET_CHAT("ClanSystem", PACKET_CHAT.ChatType.Clan, "ClanSystem >> Clan ID: " + ClanID + ", Clan Name: " + ClanName, ClanID, Nickname));
                                send(new PACKET_CHAT("ClanSystem", PACKET_CHAT.ChatType.Clan, "ClanSystem >> Clan Members: " + ClanManager.getClanMembersCount(ClanID) + "/" + ClanManager.getClanMembersMaxCount(ClanID), ClanID, Nickname));
                                send(new PACKET_CHAT("ClanSystem", PACKET_CHAT.ChatType.Clan, "ClanSystem >> Clan Master: " + ClanManager.getMasterNickname(ClanID), ClanID, Nickname));
                                send(new PACKET_CHAT("ClanSystem", PACKET_CHAT.ChatType.Clan, "ClanSystem >> Clan Wins: " + Clan.clanWarWin + " / Lose: " + Clan.clanWarLose, ClanID, Nickname));
                                send(new PACKET_CHAT("ClanSystem", PACKET_CHAT.ChatType.Clan, "ClanSystem >> Played clanwars: " + int.Parse((Clan.clanWarWin + Clan.clanWarLose).ToString()), ClanID, Nickname));
                            }
                            else
                            {
                                send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> You're not in a clan!:(", SessionID, Nickname));
                            }
                            return true;
                        }
                    case "upgrade":
                        {
                            ClanManager.UpgradeClan(this);
                            return true;
                        }
                    case "changeclanname":
                        {
                            if (args[1].Length > 0)
                                ClanManager.ChangeName(this, ClanName, args[1]);
                            return true;
                        }
                    case "createclan":
                        {
                            if (args[1].Length > 0)
                                ClanManager.AddClan(this, args[1]);
                            return true;
                        }
                    case "disbandclan":
                        {
                            ClanManager.RemoveClan(this);
                            return true;
                        }
                    case "kickfromclan":
                        {
                            if (args[1].Length > 0)
                                ClanManager.KickClan(this, args[1]);
                            return true;
                        }
                    case "leaveclan":
                        {
                            ClanManager.LeaveClan(this);
                            return true;
                        }
                    case "setclanrank":
                        {
                            if (args[1].Length > 0 && args[2].Length > 0)
                                ClanManager.SetMemberRank(this, args[1], args[2].ToLower());
                            return true;
                        }
                    case "invite":
                        {
                            if (args[1].Length > 0)
                                ClanManager.InviteMember(this, args[1]);
                            return true;
                        }
                    case "accept":
                        {
                            if (InvitationBy != -1)
                                ClanManager.JoinClan(this, InvitationBy);
                            return true;
                        }
                    case "decline":
                        {
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> Declined the invite for the clan: " + ClanManager.getClan(InvitationBy).clanName + "!!", SessionID, Nickname));
                            InvitationBy = -1;
                            return true;
                        }
                    case "ban":
                        {
                            if (Rank < 6) return false;

                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                if (Client == null) continue;

                                if (Rank > Client.Rank)
                                {
                                    if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                    {
                                        int BannedTime = 0;
                                        long Hours = int.Parse(args[2]);
                                        if (Hours > 0)
                                        {
                                            DateTime _BanCuurent = DateTime.Now;
                                            _BanCuurent = _BanCuurent.AddHours(Hours);
                                            BannedTime = int.Parse(String.Format("{0:yyMMddHH}", _BanCuurent));
                                        }
                                        else
                                        {
                                            BannedTime = -1;
                                        }
                                        DB.runQuery("UPDATE users SET bantime='" + BannedTime + "', rank='0',clanid='-1',clanrank='1' WHERE id='" + Client.UserID + "'");
                                        Log.WriteLine("---" + Nickname + " banned: " + Client.Nickname + "---");
                                        foreach (virtualUser Users in UserManager.getAllUsers())
                                            Users.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> " + Client.Nickname + " has been banned from the server by: " + Nickname + " for: " + int.Parse(args[2]) + "hours!", 999, "NULL"));
                                        Client.send(new PACKET_CHAT("Notice", PACKET_CHAT.ChatType.Notice1, "You got banned by: " + Nickname + " for: " + int.Parse(args[2]) + "hours", 100, "Notice"));
                                        Client.disconnect();
                                        return true;
                                    }
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + args[1] + " is not online or doesn't exist!", 999, "NULL"));
                            return true;
                        }
                    case "hwban":
                        {
                            if (Rank < 5) return false;

                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                if (Client == null) continue;
                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    string[] HWIDCheck = DB.runReadRow("SELECT * FROM users_hwid WHERE hwid='" + Client.HWID + "'");
                                    if (HWIDCheck.Length > 0) return true;
                                    DB.runQuery("INSERT INTO users_hwid (`hwid`) VALUES('" + Client.HWID + "')");
                                    DB.runQuery("UPDATE users SET active='0', rank='0' WHERE id='" + Client.UserID + "'");
                                    Client.disconnect();
                                    return true;
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + args[1] + " is not online or doesn't exist!", 999, "NULL"));
                            return true;
                        }
                    case "mute":
                        {
                            if (Rank < 4) return false;

                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                if (Client == null) continue;

                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    if (Rank > Client.Rank)
                                    {
                                        foreach (virtualUser Players in UserManager.getAllUsers())
                                        {
                                            Players.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + Client.Nickname + " has been muted by " + Nickname, 999, "NULL"));
                                        }
                                        Client.isMuted = true;
                                        Client.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> You Have been muted by " + Nickname + "!", 12, "SYSTEM"));
                                        return true;
                                    }
                                    else
                                    {
                                        send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> You cant mute " + Client.Nickname + " becaus he has an higer rank!", 999, "NULL"));
                                        return true;
                                    }
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + args[1] + " is not online or doesn't exist!", 999, "NULL"));
                            return true;
                        }
                    case "hwid":
                        {
                            if (Rank < 4) return false;

                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                if (Client == null) continue;
                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> The HWID of: " + Client.Nickname + " is: " + Client.HWID, 999, "NULL"));
                                    return true;
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + args[1] + " is not online or doesn't exist!", 999, "NULL"));
                            return true;
                        }
                    case "givecoupon":
                        {
                            if (Rank < 5) return false;
                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                int _CouponToAdd = int.Parse(args[2]);
                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    Client.Coupons += _CouponToAdd;
                                    DB.runQuery("UPDATE users SET coupons='" + Client.Coupons + "' WHERE id='" + Client.UserID.ToString() + "'");
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Sucessfully gaved: " + _CouponToAdd + " coupons, to: " + Client.Nickname + "!", 999, "NULL"));
                                    Client.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> You received: " + _CouponToAdd + " coupons, from: " + Nickname + "!", 999, "NULL"));
                                    return true;
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User it's not online or doesn't exist!!", 999, "NULL"));
                            return true;
                        }
                    case "givecash":
                        {
                            if (Rank < 5) return false;
                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                int _Cash = int.Parse(args[2]);
                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    Client.Cash += _Cash;
                                    DB.runQuery("UPDATE users SET cash='" + Client.Cash + "' WHERE id='" + Client.UserID.ToString() + "'");
                                    Log.WriteLine("---" + Nickname + " gaved: " + _Cash + " cashs to: " + Client.Nickname + "---");
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Sucessfully gaved: " + _Cash + " cash, to: " + Client.Nickname + "!", 999, "NULL"));
                                    Client.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> You received: " + _Cash + " cash, from: " + Nickname + "!", 999, "NULL"));
                                    return true;
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User it's not online or doesn't exist!!", 999, "NULL"));
                            return true;
                        }
                    case "givecostume":
                        {
                            if (Rank < 5) return false;
                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                string ItemCode = args[2];
                                int Days = int.Parse(args[3]);
                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    int InventorySlot = -1;
                                    for (int I = 0; I < 30; I++)
                                    {
                                        if (Client.Costume[I] == null) { InventorySlot = I; break; }
                                    }
                                    if (InventorySlot == -1) return true;
                                    if (InventorySlot >= 0)
                                    {
                                        Client.AddCostume(ItemCode, Days);
                                        Client.LoadItems();
                                        Log.WriteLine("---" + Nickname + " gaved: " + ItemCode + " to: " + Client.Nickname + " for: " + Days + " days!" + "---");
                                        send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Sucessfully gaved: " + ItemCode + ", for: " + Days + " days!", 999, "NULL"));
                                        Client.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> You received: " + ItemCode + ", for: " + Days + " days from: " + Nickname + "!", 999, "NULL"));
                                        return true;
                                    }
                                    else
                                    {
                                        send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User has not other inventory slot!", 999, "NULL"));
                                        return true;
                                    }
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User it's not online or doesn't exist!!", 999, "NULL"));
                            return true;
                        }
                    case "giveitem":
                        {
                            if (Rank < 5) return false;
                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                string ItemCode = args[2];
                                int Days = int.Parse(args[3]);
                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    int InventorySlot = -1;
                                    for (int I = 0; I < 30; I++)
                                    {
                                        if (Client.Inventory[I] == null) { InventorySlot = I; break; }
                                    }
                                    if (InventorySlot >= 0)
                                    {
                                        Client.AddItem(ItemCode, Days);
                                        Client.LoadItems();
                                        Log.WriteLine("---" + Nickname + " gaved: " + ItemCode + " to: " + Client.Nickname + " for: " + Days + " days!" + "---");
                                        send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Sucessfully gaved: " + ItemCode + ", for: " + Days + " days!", 999, "NULL"));
                                        Client.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> You received: " + ItemCode + ", for: " + Days + " days from: " + Nickname + "!", 999, "NULL"));
                                        return true;
                                    }
                                    else
                                    {
                                        send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User has not other inventory slot!", 999, "NULL"));
                                        return true;
                                    }
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User it's not online or doesn't exist!!", 999, "NULL"));
                            return true;
                        }
                    case "map":
                        {
                            if (Rank < 3) return false;
                            if (Room == null && Room.RoomStatus == 1) return true;
                            Room.MapID = int.Parse(args[1]);
                            foreach (virtualUser User in Room.Players)
                                User.send(new SP_ROOM_INFO(51, Room.RoomMasterSlot, 55, 2, 1, 0, Room.MapID, 0, 0, 0, 0, 0, 0, 0));
                            foreach (virtualUser SpectatorUser in Room.Spectators)
                                SpectatorUser.send(new SP_ROOM_INFO(51, Room.RoomMasterSlot, 55, 2, 1, 0, Room.MapID, 0, 0, 0, 0, 0, 0, 0));
                            UserManager.refreshRoom(Room);

                            return true;
                        }
                    case "event":
                        {
                            if (Rank < 5) return false;
                            Program.EventTime = int.Parse(args[1]);
                            Program.EXPEvent = int.Parse(args[2]);
                            Program.DinarEvent = int.Parse(args[2]);
                            if (int.Parse(args[1]) != -1)
                                Program.isEvent = true;
                            else
                            {
                                Program.isEvent = false;
                                Program.EventTime = -1;
                            }
                            foreach (virtualUser Player in UserManager.getAllUsers())
                            {
                                Player.send(new PACKET_PING(Player));
                                Player.send(new PACKET_EVENT_MESSAGE(PACKET_EVENT_MESSAGE.EventCodes.EXP_Activate));
                            }
                            return true;
                        }
                    case "rdis":
                        {
                            if (Rank < 3) return false;
                            int RoomToClose = int.Parse(args[1]);
                            virtualRoom TargetRoom = RoomManager.getRoom(Channel, int.Parse(args[1]));
                            if (TargetRoom != null)
                            {
                                foreach (virtualUser RoomUser in TargetRoom.Players)
                                {
                                    RoomUser.send(new PACKET_LEAVE_ROOM(RoomUser, TargetRoom, RoomUser.RoomSlot, TargetRoom.RoomMasterSlot));
                                    RoomUser.Room = null;
                                }
                                TargetRoom.remove();
                                RoomManager.removeRoom(Channel, int.Parse(args[1]));
                                return true;
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> This room doesn't exist!!", 999, "NULL"));
                            return true;

                        }
                    case "setlevel":
                        {
                            if (Rank < 6) return false;
                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    int _UserID = Client.UserID;
                                    long _Level = LevelCalculator.getExpForLevel(int.Parse(args[2]));
                                    Client.disconnect();
                                    DB.runQuery("UPDATE users SET exp='" + _Level + "' WHERE id='" + Client.UserID + "'");
                                    return true;
                                }
                            }

                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + args[1] + " is not online or doesn't exist!", 999, "NULL"));
                            return true;
                        }
                    case "roominfo":
                        {
                            if (Rank < 4) return false;
                            int RoomID = int.Parse(args[1]);
                            virtualRoom TargetRoom = RoomManager.getRoom(Channel, RoomID);
                            if (TargetRoom == null) return true;
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Here all information about room N° " + RoomID, 999, "NULL"));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Room Name: " + TargetRoom.Name, 999, "NULL"));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Password: " + TargetRoom.Password, 999, "NULL"));
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Players: " + TargetRoom.Players.Count + "/" + TargetRoom.MaxPlayers + ", Spectators " + TargetRoom.Spectators.Count + "/10", 999, "NULL"));
                            return true;
                        }
                    case "userinfo":
                        {
                            if (Rank < 4) return false;

                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                if (Client == null) continue;
                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    string rPermissions = "User";
                                    string rPremium = "Free2Play";
                                    string rChannel = "NONE";
                                    switch (Client.Rank)
                                    {
                                        case 0: rPermissions = "Banned"; break;
                                        case 1: rPermissions = "User"; break;
                                        case 2: rPermissions = "User"; break;
                                        case 3: rPermissions = "Moderator"; break;
                                        case 4: rPermissions = "Moderator"; break;
                                        case 5: rPermissions = "Administrator"; break;
                                        case 6: rPermissions = "Administrator / Leader"; break;
                                    }
                                    switch (Client.Channel)
                                    {
                                        case 1: rChannel = "Close Quarter Combat"; break;
                                        case 2: rChannel = "Urban Ops"; break;
                                        case 3: rChannel = "Battle Group"; break;
                                        case 4: rChannel = "A.I Mode"; break;
                                    }
                                    switch (Client.Premium)
                                    {
                                        case 0: rPremium = "Free2Play"; break;
                                        case 1: rPremium = "Bronze"; break;
                                        case 2: rPremium = "Silver"; break;
                                        case 3: rPremium = "Gold"; break;
                                        case 4: rPremium = "Platinum"; break;
                                    }
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Here all information about: " + Client.Nickname + " with ID: " + Client.UserID, 999, "NULL"));
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> UserID: " + Client.Username + ", Nickname: " + Client.Nickname, 999, "NULL"));
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Kills: " + Client.Kills + ", Deaths: " + Client.Deaths, 999, "NULL"));
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Dinars: " + Client.Dinar + ", Cash: " + Client.Cash, 999, "NULL"));
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Level: " + LevelCalculator.getLevelforExp(Client.Exp) + ", Rank: " + Client.Rank, 999, "NULL"));
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Actual Channel: " + rChannel, 999, "NULL"));
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Premium: " + rPremium + ", PremiumID: " + Client.Premium, 999, "NULL"));
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Rank: " + Client.Rank, 999, "NULL"));
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Permissions: " + rPermissions, 999, "NULL"));
                                    send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> HWID: " + Client.HWID + ", IP: " + Client.IPAddr, 999, "NULL"));
                                    return true;
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + args[1] + " is not online or doesn't exist!", 999, "NULL"));
                            return true;
                        }
                    case "unmute":
                        {
                            if (Rank < 4) return false;

                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                if (Client == null) continue;

                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    if (Rank > Client.Rank)
                                    {
                                        if (Client.isMuted != false)
                                        {
                                            foreach (virtualUser Players in UserManager.getAllUsers())
                                            {
                                                Players.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + Client.Nickname + " has been unmuted by " + Nickname + "!", 999, "NULL"));
                                            }
                                            Client.isMuted = false;
                                            Client.MutedTime = -1;
                                            DB.runQuery("UPDATE users SET muted='0', mutedExpire ='-1' WHERE id='" + Client.UserID + "'");
                                            Client.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Whisper, "SYSTEM >> You Have been unmuted by " + Nickname + "!", 12, "SYSTEM"));
                                            return true;
                                        }
                                        else
                                        {
                                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + Client.Nickname + " is not muted!", 999, "NULL"));
                                        }
                                    }
                                    else
                                    {
                                        send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> You cant unmute " + Client.Nickname + " becaus he has an higer rank!", 999, "NULL"));
                                        return true;
                                    }
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + args[1] + " is not online or doesn't exist!", 999, "NULL"));
                            return true;
                        }
                    case "kickr":
                        {
                            if (Rank < 3) return false;
                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                if (Client == null) continue;

                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    if (Client.Room == null) return true;
                                    Client.Room.removeUser(Client.RoomSlot);
                                    return true;
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + args[1] + " is not online or doesn't exist!", 999, "Server"));
                            return true;
                        }
                    case "kick":
                        {
                            if (Rank < 3) return false;

                            foreach (virtualUser Client in UserManager.getAllUsers())
                            {
                                if (Client == null) continue;

                                if (Client.Nickname.ToLower().Equals(args[1].ToLower()) || Client.Username.ToLower().Equals(args[1].ToLower()))
                                {
                                    if (Rank >= Client.Rank)
                                    {
                                        foreach (virtualUser Serv in UserManager.getAllUsers())
                                        {
                                            Serv.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + Client.Nickname + " got kicked from the server by " + Nickname + "!", 999, "Server"));
                                        }
                                        Client.disconnect();
                                        return true;
                                    }
                                    else
                                    {
                                        send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> You cant kick " + Client.Nickname + " becaus he has an higer rank!", 999, "Server"));
                                        return true;
                                    }
                                }
                            }
                            send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> User " + args[1] + " is not online or doesn't exist!", 999, "Server"));
                            return true;
                        }
                    case "stop":
                        {
                            try
                            {
                                if (Rank < 6) return false;
                                foreach (virtualUser Player in UserManager.getAllUsers())
                                {
                                    Player.send(new PACKET_CHAT("Server", PACKET_CHAT.ChatType.Notice1, "NOTICE: Server it's going to be restarted, sorry!!!", 100, "NULL"));
                                    Player.send(new PACKET_CHAT("SYSTEM", PACKET_CHAT.ChatType.Room_ToAll, "SYSTEM >> Server it's going to be restarted, sorry!!!", 999, "Server"));
                                }
                                Thread.Sleep(500);
                                Program.shutDown();
                                return true;
                            }
                            catch { return false; }
                        }
                    default: { return false; }
                }
            }
            catch { return false; }

            return true;
        }
        #endregion

        #region Networking

        public int iSocketID { get { return SocketID; } }

        private int SocketID;
        public Socket uSocket;
        private byte[] dataBuffer = new byte[1024];
        private bool isDisconnected = false;
        public bool pingOK = false;
        public long Ping = 0;

        public long nIP = 0;
        public int nPort = 0;
        public long lIP = 0;
        public int lPort = 0;
        public int PortToInt(int Port)
        {
            try
            {
                byte[] PortBytes = BitConverter.GetBytes(Port);
                byte[] PortBytesNew = new byte[2] { PortBytes[1], PortBytes[0] };
                ushort newPort = BitConverter.ToUInt16(PortBytesNew, 0);

                return newPort;
            }
            catch (Exception ex)
            {
                Log.WriteLine("Error on PortToInt: " + ex.Message);
                return -1;
            }
        }

        public String IPAddr { get { return uSocket.RemoteEndPoint.ToString().Split(':')[0]; } }
        public String Hostname { get { return Dns.GetHostEntry(this.IPAddr).HostName; } }

        public string ReverseIP(string tString)
        {
            try
            {
                string[] bString = tString.Split(new char[] { '.' });
                string tNew = "";
                for (int i = (bString.Length - 1); i > -1; i--)
                    tNew += bString[i] + ".";
                return tNew.Substring(0, tNew.Length - 1);
            }
            catch (Exception ex)
            {
                Log.WriteLine("Error on ReverseIP: " + ex.Message);
                return null;
            }
        }

        public long IPToInt(string addr)
        {
            try
            {
                return (long)(uint)IPAddress.NetworkToHostOrder((int)IPAddress.Parse(ReverseIP(addr)).Address);
            }
            catch (Exception ex)
            {
                Log.WriteLine("Error on IPToInt: " + ex.Message);
                return -1;
            }
        }
        public void SetUpNetwork(IPEndPoint GroupEP, byte UDPId)
        {
            try
            {
                nIP = IPToInt(GroupEP.Address.ToString());
                nPort = PortToInt(GroupEP.Port);
                Log.WriteDebug(string.Concat(new object[] { "Setting Up Network! UDPID: ", UDPId, " (nIP: ", this.lNetworkIP, ":", this.iNetworkPort, " lIP: ", this.lLocalIP, ":", this.iLocalPort }));
            }
            catch (Exception ex)
            {
                Log.WriteError("Error on SetUpNetwork: " + ex.Message);
            }
        }

        public bool isDefaultWeapon(string Weapon)
        {
            if (Weapon == "DF01" || Weapon == "DQ01" || Weapon == "DR01" || hasRetail(Weapon) || /* Retail part */ Weapon == "DF02" || Weapon == "DB03" /*end retail part*/|| Weapon == "DN01" || Weapon == "DC02" || Weapon == "DG05" || Weapon == "DB01" || Weapon == "DL01" || Weapon == "DJ01" || Weapon == "DA02")
                return true;
            return false;
        }

        public int getInventoryID(string WeaponCode)
        {
            for (int I = 0; I < Inventory.Length; I++)
            {
                InventoryItem Item = Inventory[I];
                if (Item != null)
                {
                    if (Item._Code.ToUpper() == WeaponCode.ToUpper())
                        return I;
                }
            }
            return -1;
        }

        #region Arrival

        private void arrivedData(IAsyncResult iAr)
        {
            try
            {
                int DataLength = uSocket.EndReceive(iAr);

                if (DataLength > 1)
                {
                    byte[] packetBuffer = new byte[DataLength];
                    Array.Copy(dataBuffer, 0, packetBuffer, 0, DataLength);

                    /* Decode Packet */
                    for (int I = 0; I < packetBuffer.Length; I++)
                    {
                        packetBuffer[I] = (byte)(packetBuffer[I] ^ 0x45); // - Original 
                        //packetBuffer[I] = Convert.ToByte((int)(Convert.ToByte((int)(Convert.ToByte((int)(packetBuffer[I] ^ 0xc3)) ^ 0xE6)) ^ 0x60));
                    }

                    PacketHandler pHandler = PacketManager.parsePacket(packetBuffer);

                    if (pHandler != null)
                    {
                        pHandler.Handle(this);
                    }
                }

                uSocket.BeginReceive(dataBuffer, 0, dataBuffer.Length, SocketFlags.None, new AsyncCallback(arrivedData), null);
            }
            catch { disconnect(); }
        }

        #endregion

        #region Send

        public void send(Packet p)
        {
            byte[] sendBuffer = p.getBytes();
            try { uSocket.BeginSend(sendBuffer, 0, sendBuffer.Length, SocketFlags.None, new AsyncCallback(sendCallBack), null); }
            catch { disconnect(); }
        }

        private void sendCallBack(IAsyncResult iAr)
        {
            try { uSocket.EndSend(iAr); }
            catch { disconnect(); }
        }

        #endregion

        #region Disconnect
        public void disconnect()
        {
            try
            {
                if (isDisconnected) return;

                isDisconnected = true;

                if (Room != null)
                {
                    if (isSpectating == false)
                        Room.removeUser(RoomSlot);
                    else
                        Room.removeSpectator(this);
                }

                UserManager.removeUser(this);

                NetworkSocket.freeSlot(SocketID, this.IPAddr, this.Hostname);
            }
            catch { }

            try { uSocket.Close(); }
            catch { }
        }
        #endregion

        #endregion

        #region Tunneling & Peer2Peer

        public IPEndPoint remoteEndPoint { get { return _RemoteEndPoint; } }
        public IPEndPoint localEndPoint { get { return _LocalEndPoint; } }

        public void setRemoteEndPoint(IPEndPoint Target)
        {
            try
            {
                nIP = IPToInt(Target.Address.ToString());
                nPort = PortToInt(Target.Port);
                _RemoteEndPoint = Target;
            }
            catch (Exception ex)
            {
                Log.WriteError("Some error on setRemoteEndPoint: " + ex.Message);
            }
        }

        public void setLocalEndPoint(IPEndPoint Target)
        {
            try
            {
                lIP = IPToInt(Target.Address.ToString());
                lPort = PortToInt(Target.Port);
                _LocalEndPoint = Target;
            }
            catch (Exception ex)
            {
                Log.WriteError("Some error on setLocalEndPoint: " + ex.Message);
            }
        }

        #endregion
    }
}
